﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using AutoMapper;
using K9Nano.Application.Organization.Dto;
using K9Nano.Dependency;
using K9Nano.Domain;
using K9Nano.Organization;
using K9Nano.Runtime;
using Microsoft.Extensions.Logging;

namespace K9Nano.Application.Organization
{
    public class OrganizationUnitAppService: K9ApplicationService, IScopedDependency
    {
        private readonly OrganizationUnitManager _organizationUnitManager;

        public OrganizationUnitAppService(IUnitOfWork uow, IMapper mapper, ISessionContext sessionContext, ILoggerFactory loggerFactory, OrganizationUnitManager organizationUnitManager) : base(uow, mapper, sessionContext, loggerFactory)
        {
            _organizationUnitManager = organizationUnitManager;
        }

        public async Task<OrganizationUnitDto> CreateAsync(OrganizationUnitCreateInput input, CancellationToken cancellation)
        {
            var ou = Mapper.Map<OrganizationUnit>(input);
            await _organizationUnitManager.CreateAsync(ou, cancellation);
            var dto = Mapper.Map<OrganizationUnitDto>(ou);
            return dto;
        }

        public async Task<OrganizationUnitDto> UpdateAsync(OrganizationUnitUpdateInput input, CancellationToken cancellation)
        {
            var ou = Mapper.Map<OrganizationUnit>(input);
            await _organizationUnitManager.UpdateAsync(ou, cancellation);
            var dto = Mapper.Map<OrganizationUnitDto>(ou);
            return dto;
        }

        public async Task DeleteAsync(Guid id, CancellationToken cancellation)
        {
            await _organizationUnitManager.DeleteAsync(id, cancellation);
        }

        public async Task<IReadOnlyList<OrganizationUnitDto>> GetChildrenAsync(Guid? parentId, bool recursive, CancellationToken cancellation)
        {
            var children = await _organizationUnitManager.FindChildrenAsync(parentId, recursive, cancellation);
            if (children.Count == 0)
            {
                return new OrganizationUnitDto[0];
            }

            return Mapper.Map<List<OrganizationUnitDto>>(children);
        }

        public async Task<OrganizationUnitDto> GetAsync(Guid id, CancellationToken cancellation)
        {
            var ou = await _organizationUnitManager.GetAsync(id, cancellation);

            var dto = Mapper.Map<OrganizationUnitDto>(ou);

            return dto;
        }
    }
}